import datetime
import logging
import json
import os
import subprocess
import tempfile
import toml

import pytz
from absl import app, flags

from coin.base.hostname import get_hostname
from coin.base.param_util import filter_duplicate, split_string
from xunkemgmt_client.client.util.query_util import query_accounts


FLAGS = flags.FLAGS

mea_channel_map = {
  ('Spot', 'Binance'): ['bbo'],
  ('Spot', 'Bithumb'): ['book', 'snapshot'],
  ('Spot', 'Gateio'): ['snapshot', 'trade'],
  ('Spot', 'Gdax'): ['level2'],
  ('Spot', 'Huobi'): ['bbo'],
  ('Spot', 'Kraken'): ['book'],
  ('Spot', 'Mexc'): ['snapshot', 'trade'],
  ('Spot', 'Okex'): ['bbo'],
  ('Spot', 'Phemex'): ['book'],
}


def _validate_sub_request(sub_request):
  assert sub_request.market_type is not None
  assert sub_request.exchange is not None
  assert sub_request.api_version is not None


def sub_requests_to_driver_dict(sub_requests):
  mea_config_dict = {}
  for sub_request in sub_requests:
    _validate_sub_request(sub_request)
    market_type = sub_request.market_type
    exchange = sub_request.exchange
    api_version = sub_request.api_version
    mea = f'{market_type}.{exchange}.{api_version}'
    assert mea not in mea_config_dict, mea
    symbol_group_file = f'data/coin2/feed/symbol_groups.toml'
    with open(symbol_group_file) as f:
      symbol_groups_universe = toml.load(f)
      symbol_groups = [*(symbol_groups_universe[mea.lower().replace('.', '_')].keys())]
    websocket_config = {"timeout": 10000000000}
    if exchange == "Mexc":
      websocket_config.update({"unauthorized_limit": {"subscription_rate": "1/3S"}})
    mea_config_dict[mea] = {
      'channels': mea_channel_map[(market_type, exchange)],
      'products': {'groups': symbol_groups},
      "websocket": websocket_config
    }
  common_config = {
    "type": "FEED_SYSTEM_TYPE_LIVE",
    "websocket": {
        "num_workers": 1,
        "worker_id": 1
    }
  }
  driver = {
    'feed': {
      'common': common_config,
      'exchanges': mea_config_dict
    },
    'executor': {"live": {"parser_threads": 5}}
  }
  return driver


def collect_market_info(request_list):
  if len(request_list) == 0:
    return
  os.makedirs(FLAGS.log_dir, exist_ok=True)
  driver_dict = sub_requests_to_driver_dict(request_list)
  dt_str = datetime.datetime.utcnow().replace(tzinfo=pytz.UTC).strftime(
        '%Y%m%d-%H%M%S%z')
  log_file = os.path.join(
      FLAGS.log_dir,
      f'market_info_collector.{dt_str}')
  out_driver_json = tempfile.mkstemp(
      dir='/tmp', prefix=f'driver_config.', suffix='.json')[-1]
  with open(out_driver_json, 'w') as fwrite:
    json.dump(driver_dict, fwrite, indent=2, sort_keys=True)
  cmd = 'source ${HOME}/miniconda3/etc/profile.d/conda.sh' + ' && ' + \
        'conda activate %s' % FLAGS.env + ' && ' + \
        'export GLOG_logtostderr=1' + ' && cd .. && ' + \
        FLAGS.binary_path + ' ' + \
        '--driver %s --out_dir %s --machine %s > %s 2>&1' % (
            out_driver_json,
            os.path.join(os.path.expanduser('~'),'data/sub_proto_log'),
            get_hostname(),
            log_file)
  subprocess.run(cmd, shell=True, check=True)


def main(_):
  logging.info('start market info collection')
  request_list = query_accounts(
      active=True,
      market_types=split_string(FLAGS.market_type),
      exchanges=split_string(FLAGS.exchange),
      as_proto=True)
  request_list = filter_duplicate(
      request_list,
      key_func=lambda x: (x.market_type, x.exchange, x.api_version))
  collect_market_info(request_list)


if __name__ == '__main__':
  logging.basicConfig(level='INFO', format='%(levelname)8s %(asctime)s %(message)s')

  flags.DEFINE_string('market_type', None, 'Comma separated market_type.')

  flags.DEFINE_string('exchange', None, 'Comma separated exchange.')

  flags.DEFINE_string('env', 'coin2_motion_env_migration', 'conda enviroment')

  flags.DEFINE_string('binary_path',
                      '../coin_binary/coin2-bazel-bin-3.10/cc/appcoin2/support/feed/ticker_generator',
                      'collector binary path')

  app.run(main)
